<html lang="zh-CN"><head><meta charset="UTF-8"><style>.nodata  main {width:1000px;margin: auto;}</style></head><body class="nodata " style=""><div class="main_father clearfix d-flex justify-content-center " style="height:100%;"> <div class="container clearfix " id="mainBox"><main><div class="blog-content-box">
<div class="article-header-box">
<div class="article-header">
<div class="article-title-box">
<h1 class="title-article" id="articleContentId">(A卷,200分)- 任务调度（Java & JS & Python）</h1>
</div>
</div>
</div>
<div id="blogHuaweiyunAdvert"></div>

        <div id="article_content" class="article_content clearfix">
        <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
        <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-044f2cf1dc.css">
                <div id="content_views" class="htmledit_views">
                    <h4 id="main-toc">题目描述</h4> 
<p>现有一个CPU和一些任务需要处理&#xff0c;已提前获知每个任务的任务ID、优先级、所需执行时间和到达时间。<br /> CPU同时只能运行一个任务&#xff0c;请编写一个任务调度程序&#xff0c;采用“可抢占优先权调度”调度算法进行任务调度&#xff0c;规则如下&#xff1a;</p> 
<ul><li>如果一个任务到来时&#xff0c;CPU是空闲的&#xff0c;则CPU可以运行该任务直到任务执行完毕。但是如果运行中有一个更高优先级的任务到来&#xff0c;则CPU必须暂停当前任务去运行这个优先级更高的任务&#xff1b;</li><li>如果一个任务到来时&#xff0c;CPU正在运行一个比他优先级更高的任务时&#xff0c;新到达的任务必须等待&#xff1b;</li><li>当CPU空闲时&#xff0c;如果还有任务在等待&#xff0c;CPU会从这些任务中选择一个优先级最高的任务执行&#xff0c;相同优先级的任务选择到达时间最早的任务。</li></ul> 
<p></p> 
<h4 id="%E8%BE%93%E5%85%A5%E6%8F%8F%E8%BF%B0">输入描述</h4> 
<p>输入有若干行&#xff0c;每一行有四个数字&#xff08;均小于10^8&#xff09;,分别为任务ID&#xff0c;任务优先级&#xff0c;执行时间和到达时间。</p> 
<p>每个任务的任务ID不同&#xff0c;优先级数字越大优先级越高&#xff0c;并且相同优先级的任务不会同时到达。</p> 
<p>输入的任务已按照到达时间从小到大排序&#xff0c;并且保证在任何时间&#xff0c;处于等待的任务不超过10000个。</p> 
<p></p> 
<h4 id="%E8%BE%93%E5%87%BA%E6%8F%8F%E8%BF%B0">输出描述</h4> 
<p>按照任务执行结束的顺序&#xff0c;输出每个任务的任务ID和对应的结束时间。</p> 
<p></p> 
<h4 id="%E7%94%A8%E4%BE%8B">用例</h4> 
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;"><tbody><tr><td style="width:86px;">输入</td><td style="width:412px;">1 3 5 1<br /> 2 1 5 10<br /> 3 2 7 12<br /> 4 3 2 20<br /> 5 4 9 21<br /> 6 4 2 22</td></tr><tr><td style="width:86px;">输出</td><td style="width:412px;">1 6<br /> 3 19<br /> 5 30<br /> 6 32<br /> 4 33<br /> 2 35</td></tr><tr><td style="width:86px;">说明</td><td style="width:412px;">无</td></tr></tbody></table> 
<p></p> 
<h4 id="%E9%A2%98%E7%9B%AE%E8%A7%A3%E6%9E%90">题目解析</h4> 
<p>用例图示如下</p> 
<p><img alt="" height="494" src="https://img-blog.csdnimg.cn/ab7cf224eaa64f6488a9d875410899ac.png" width="1200" /></p> 
<p>task1在1时刻到达&#xff0c;此时CPU空闲&#xff0c;因此执行task1&#xff0c;task1需要执行5个时间&#xff0c;而执行期间没有新任务加入&#xff0c;因此task1首先执行完成&#xff0c;<span style="color:#fe2c24;">结束时刻是6</span>。</p> 
<p>task2在10时刻达到&#xff0c;此时CPU空闲&#xff0c;因此执行task2&#xff0c;task2需要执行5个时间&#xff0c;但是在task2执行到12时刻时&#xff0c;有新任务task3加入&#xff0c;且优先级更高&#xff0c;因此task2让出执行权&#xff0c;<span style="color:#a2e043;">task2还需要5-&#xff08;12-10&#xff09;&#61; 3 个时间才能执行完</span>&#xff0c;task2进入等待队列。</p> 
<p>task3在12时刻到达&#xff0c;此时CPU正在执行task2&#xff0c;但是由于task3的优先级高于task2&#xff0c;因此task3获得执行权开始执行&#xff0c;task3需要7个时间&#xff0c;而在下一个任务task4会在20时刻到达&#xff0c;因此task3可以执行完&#xff0c;<span style="color:#fe2c24;">结束时刻是19</span>。</p> 
<p>task3执行结束时刻是19&#xff0c;而task4到达时间是20&#xff0c;因此中间有一段CPU空闲期&#xff0c;而等待队列中还有一个task2等待执行&#xff0c;因此此时CPU会调出task2继续执行&#xff0c;但是只能执行1时间&#xff0c;<span style="color:#a2e043;">因此task2还需要3 - 1 &#61; 2个时间才能执行完</span>。</p> 
<p>task4在20时刻到达&#xff0c;此时CPU正在执行task2&#xff0c;但是由于task4的优先级更高&#xff0c;因此task4获得执行权开始执行&#xff0c;task2重回等待队列&#xff0c;task4需要2个时间&#xff0c;但是执行到时刻21时&#xff0c;task5到达了&#xff0c;且优先级更高&#xff0c;因此<span style="color:#a2e043;">task4还需2 - (21-20) &#61; 1 个时间才能执行完</span>&#xff0c;task4进入等待队列。</p> 
<p>此时等待队列有两个任务task2&#xff0c;task4&#xff0c;因此需要按照优先级排序&#xff0c;优先级高的在队头&#xff0c;因此queue &#61; [task4, task2]</p> 
<p>task5在21时刻到达&#xff0c;此时CPU正在执行task4&#xff0c;但是task5的优先级更高&#xff0c;因此task5获得执行权开始执行&#xff0c;task4进入等待队列&#xff0c;task5需要9个时间&#xff0c;但是执行到时刻22时&#xff0c;task6到达了&#xff0c;但是task6的优先级和task5相同&#xff0c;因此task5执行不受影响&#xff0c;task5会在21 &#43; 9 &#61;<span style="color:#fe2c24;"> 30 时刻执行完成</span>。</p> 
<p>而task6则进入等待队列&#xff0c;有新任务进入队列后&#xff0c;就要按优先级重新排序&#xff0c;优先级高的在队头&#xff0c;因此queue &#61; [task6, task4, task2]。</p> 
<p></p> 
<p>此时所有任务已经遍历完&#xff0c;我们检查等待队列是否有任务&#xff0c;若有&#xff0c;则此时任务队列中的任务必然是按优先级降序的&#xff0c;因此我们依次取出队头任务&#xff0c;在上一次结束时刻基础上添加需要的时间&#xff0c;就是新的结束时刻&#xff0c;比如</p> 
<p>task6出队&#xff0c;上一次结束时刻是30&#xff0c;因此task6的结束时刻 &#61; 30 &#43; 2 &#61; 32&#xff0c;新的结束时刻变为32</p> 
<p>task4出队&#xff0c;上一次结束时刻是32&#xff0c;因此task4的结束时刻 &#61; 32 &#43; 1 &#61; 33&#xff0c;新的结束时刻变为33</p> 
<p>task2出队&#xff0c;上一次结束时刻是33&#xff0c;因此task2的结束时刻 &#61; 33 &#43; 2 &#61; 35&#xff0c;新的结束时刻变为33。</p> 
<p></p> 
<p>本题实现的难点在于&#xff1a;</p> 
<p>1、等待队列的实现</p> 
<p>这里的等待队列其实就是优先队列&#xff0c;优先队列我们可以基于有序数组实现&#xff0c;但是有序数组实现最优先队列的时间复杂度至少O(n)&#xff0c;算是比较高的。优先队列其实只要每次保证最高优先级的任务处于队头即可&#xff0c;无需实现整体有序&#xff0c;因此基于最大堆实现优先队列是更好的选择&#xff0c;最大堆每次实现优先队列&#xff0c;只需要O(logN)的时间复杂度&#xff0c;因此在处理大数量级是更具有优势&#xff0c;但是JS语言并没有实现基于堆结构的优先队列&#xff0c;因此我们需要手动实现&#xff0c;相较于有序数组而言&#xff0c;难度较大。关于基于堆的优先队列实现&#xff0c;请看&#xff1a;<a href="https://blog.csdn.net/qfc_128220/article/details/127695013" title="LeetCode - 1705 吃苹果的最大数目_伏城之外的博客-CSDN博客">LeetCode - 1705 吃苹果的最大数目_伏城之外的博客-CSDN博客</a></p> 
<p>2、CPU的任务执行逻辑</p> 
<p>CPU执行某个任务时&#xff0c;如果有新任务加入&#xff0c;则我们应该比较正在执行的任务和新任务的优先级&#xff0c;</p> 
<ul><li>如果新任务优先级较高&#xff0c;则应该将正在执行的任务撤出&#xff0c;加入到等待队列中&#xff0c;然后执行新任务。</li><li>如果新任务优先级不高于正在执行的任务&#xff0c;则新任务进入等待队列&#xff0c;继续执行当前任务。</li></ul> 
<p><s>CPU空转期间&#xff0c;应该检查等待队列是否有任务&#xff0c;并取出最高优先级任务执行。</s></p> 
<p></p> 
<p>2023.02.19 根据网友反馈上面逻辑的通过率为20%&#xff0c;我重新看了一下&#xff0c;发现上面遗漏一个逻辑&#xff1a;</p> 
<p>题目说</p> 
<blockquote> 
 <p>当CPU空闲时&#xff0c;如果还有任务在等待&#xff0c;CPU会从这些任务中选择一个优先级最高的任务执行&#xff0c;<span style="color:#fe2c24;">相同优先级的任务选择到达时间最早的任务</span>。</p> 
</blockquote> 
<p>而上面逻辑中遗漏考虑了相同优先级时&#xff0c;按照到达时间为第二优先级来安排任务执行的场景。已修复。</p> 
<p></p> 
<h4 id="%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81">JavaScript算法源码</h4> 
<p>基于最大堆实现优先队列</p> 
<pre><code class="language-javascript">/* JavaScript Node ACM模式 控制台输入获取 */
const readline &#61; require(&#34;readline&#34;);

const rl &#61; readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines &#61; [];
rl.on(&#34;line&#34;, (line) &#61;&gt; {
  if (line !&#61;&#61; &#34;&#34;) {
    lines.push(line);
  } else {
    const tasks &#61; lines.map((line) &#61;&gt; line.split(&#34; &#34;).map(Number));
    getResult(tasks);
    lines.length &#61; 0;
  }
});

/**
 *
 * &#64;param {*} tasks 二维数组&#xff0c;元素组数含义是[任务ID&#xff0c;任务优先级&#xff0c;执行时间&#xff0c;到达时间]
 */
function getResult(tasks) {
  tasks &#61; tasks.map((task) &#61;&gt; {
    return { id: task[0], priority: task[1], need: task[2], arrived: task[3] };
  });

  const pq &#61; new Pqueue((a, b) &#61;&gt;
    a.priority !&#61; b.priority ? b.priority - a.priority : a.arrived - b.arrived
  );

  pq.offer(tasks.shift());
  let curTime &#61; pq.peek().arrived; // curTime记录当前时刻

  while (tasks.length &gt; 0) {
    const curtTask &#61; pq.peek(); // 当前正在运行的任务curtTask
    const nextTask &#61; tasks.shift(); // 下一个任务nextTask

    const curTask_endTime &#61; curTime &#43; curtTask.need; // 当前正在运行任务的“理想”结束时间

    // 如果当前正在运行任务的理想结束时间  超过了  下一个任务的开始时间
    if (curTask_endTime &gt; nextTask.arrived) {
      curtTask.need -&#61; nextTask.arrived - curTime; // 先不看优先级&#xff0c;先将当前任务可以运行的时间减去
      curTime &#61; nextTask.arrived;
    }
    // 如果当前正在运行任务的理想结束时间  没有超过  下一个任务的开始时间&#xff0c;则当前任务可以执行完
    else {
      pq.poll();
      console.log(&#96;${curtTask.id} ${curTask_endTime}&#96;); // 打印执行完的任务的id和结束时间
      curTime &#61; curTask_endTime;

      // 如果当前任务结束时&#xff0c;下一次任务还没有达到&#xff0c;那么存在CPU空转(即idle)
      if (nextTask.arrived &gt; curTask_endTime) {
        // 此时&#xff0c;我们应该从优先队列中取出最优先的任务出来执行&#xff0c;逻辑同上
        while (pq.size &gt; 0) {
          const idleTask &#61; pq.peek();
          const idleTask_endTime &#61; curTime &#43; idleTask.need;

          if (idleTask_endTime &gt; nextTask.arrived) {
            idleTask.need -&#61; nextTask.arrived - curTime;
            break;
          } else {
            pq.poll();
            console.log(&#96;${idleTask.id} ${idleTask_endTime}&#96;);
            curTime &#61; idleTask_endTime;
          }
        }
        curTime &#61; nextTask.arrived;
      }
    }

    pq.offer(nextTask);
  }

  // 所有任务都加入优先队列后&#xff0c;我们就可以按照优先队列的安排&#xff0c;顺序取出任务来执行了
  while (pq.size &gt; 0) {
    const pollTask &#61; pq.poll();
    const pollTask_endTime &#61; curTime &#43; pollTask.need;
    console.log(&#96;${pollTask.id} ${pollTask_endTime}&#96;);
    curTime &#61; pollTask_endTime;
  }
}

// 基于堆实现优先队列
class Pqueue {
  constructor(cpr) {
    this.queue &#61; [];
    this.size &#61; 0;
    this.cpr &#61; cpr;
  }

  swap(i, j) {
    let tmp &#61; this.queue[i];
    this.queue[i] &#61; this.queue[j];
    this.queue[j] &#61; tmp;
  }

  // 上浮
  swim() {
    let ch &#61; this.queue.length - 1;

    while (ch !&#61;&#61; 0) {
      let fa &#61; Math.floor((ch - 1) / 2);

      const ch_node &#61; this.queue[ch];
      const fa_node &#61; this.queue[fa];

      if (this.cpr(ch_node, fa_node) &lt; 0) {
        this.swap(ch, fa);
        ch &#61; fa;
      } else {
        break;
      }
    }
  }

  // 下沉
  sink() {
    let fa &#61; 0;

    while (true) {
      let ch_left &#61; 2 * fa &#43; 1;
      let ch_right &#61; 2 * fa &#43; 2;

      let ch_max;
      let ch_max_node;

      const fa_node &#61; this.queue[fa];
      const ch_left_node &#61; this.queue[ch_left];
      const ch_right_node &#61; this.queue[ch_right];

      if (ch_left_node &amp;&amp; ch_right_node) {
        // 注意这里应该要&gt;&#61;0&#xff0c;因为左边优先级高
        if (this.cpr(ch_left_node, ch_right_node) &lt;&#61; 0) {
          ch_max &#61; ch_left;
          ch_max_node &#61; ch_left_node;
        } else {
          ch_max &#61; ch_right;
          ch_max_node &#61; ch_right_node;
        }
      } else if (ch_left_node &amp;&amp; !ch_right_node) {
        ch_max &#61; ch_left;
        ch_max_node &#61; ch_left_node;
      } else if (!ch_left_node &amp;&amp; ch_right_node) {
        ch_max &#61; ch_right;
        ch_max_node &#61; ch_right_node;
      } else {
        break;
      }

      // 注意这里应该要&gt;0&#xff0c;因为父优先级高
      if (this.cpr(ch_max_node, fa_node) &lt; 0) {
        this.swap(ch_max, fa);
        fa &#61; ch_max;
      } else {
        break;
      }
    }
  }

  // 向优先队列中加入元素
  offer(ele) {
    this.queue.push(ele);
    this.size&#43;&#43;;
    this.swim();
  }

  // 取出最高优先级元素
  poll() {
    this.swap(0, this.queue.length - 1);
    this.size--;
    const ans &#61; this.queue.pop();
    this.sink();
    return ans;
  }

  // 只使用最高优先级元素&#xff0c;不取出
  peek() {
    return this.queue[0];
  }
}
</code></pre> 
<p></p> 
<h4>Java算法源码</h4> 
<p> Java已有专门的优先队列实现类PriorityQueue&#xff0c;因此我们可以直接使用它&#xff0c;而不需要自己实现。</p> 
<pre><code class="language-java">import java.util.Arrays;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc &#61; new Scanner(System.in);

    LinkedList&lt;Task&gt; list &#61; new LinkedList&lt;&gt;();

    while (sc.hasNextLine()) {
      String s &#61; sc.nextLine();
      if (&#34;&#34;.equals(s)) break;
      Integer[] arr &#61; Arrays.stream(s.split(&#34; &#34;)).map(Integer::parseInt).toArray(Integer[]::new);
      Task task &#61; new Task(arr[0], arr[1], arr[2], arr[3]);
      list.add(task);
    }

    getResult(list);
  }

  /**
   * &#64;param tasks 任务列表
   */
  public static void getResult(LinkedList&lt;Task&gt; tasks) {
    PriorityQueue&lt;Task&gt; pq &#61;
        new PriorityQueue&lt;&gt;(
            (a, b) -&gt; a.priority !&#61; b.priority ? b.priority - a.priority : a.arrived - b.arrived);

    pq.offer(tasks.removeFirst());
    int curTime &#61; pq.peek().arrived; // curTime记录当前时刻

    while (tasks.size() &gt; 0) {
      Task curtTask &#61; pq.peek(); // 当前正在运行的任务curtTask
      Task nextTask &#61; tasks.removeFirst(); // 下一个任务nextTask

      int curtTask_endTime &#61; curTime &#43; curtTask.need; // 当前正在运行任务的“理想”结束时间

      if (curtTask_endTime &gt; nextTask.arrived) { // 如果当前正在运行任务的理想结束时间  超过了  下一个任务的开始时间
        curtTask.need -&#61; nextTask.arrived - curTime; // 先不看优先级&#xff0c;先将当前任务可以运行的时间减去
        curTime &#61; nextTask.arrived;
      } else { // 如果当前正在运行任务的理想结束时间  没有超过  下一个任务的开始时间&#xff0c;则当前任务可以执行完
        pq.poll(); // 当前任务出队
        System.out.println(curtTask.id &#43; &#34; &#34; &#43; curtTask_endTime); // 打印执行完的任务的id和结束时间
        curTime &#61; curtTask_endTime;

        if (nextTask.arrived &gt; curtTask_endTime) { // 如果当前任务结束时&#xff0c;下一次任务还没有达到&#xff0c;那么存在CPU空转(即idle)
          while (pq.size() &gt; 0) { // 此时&#xff0c;我们应该从优先队列中取出最优先的任务出来执行&#xff0c;逻辑同上
            Task idleTask &#61; pq.peek();
            int idleTask_endTime &#61; curTime &#43; idleTask.need;

            if (idleTask_endTime &gt; nextTask.arrived) {
              idleTask.need -&#61; nextTask.arrived - curTime;
              break;
            } else {
              pq.poll();
              System.out.println(idleTask.id &#43; &#34; &#34; &#43; idleTask_endTime);
              curTime &#61; idleTask_endTime;
            }
          }
          curTime &#61; nextTask.arrived;
        }
      }

      pq.offer(nextTask);
    }

    // 所有任务都加入优先队列后&#xff0c;我们就可以按照优先队列的安排&#xff0c;顺序取出任务来执行了
    while (pq.size() &gt; 0) {
      Task pollTask &#61; pq.poll();
      int pollTask_endTime &#61; curTime &#43; pollTask.need;
      System.out.println(pollTask.id &#43; &#34; &#34; &#43; pollTask_endTime);
      curTime &#61; pollTask_endTime;
    }
  }
}

class Task {
  int id; // 任务id
  int priority; // 任务优先级
  int need; // 任务执行时长
  int arrived; // 任务到达时刻

  public Task(int id, int priority, int need, int arrived) {
    this.id &#61; id;
    this.priority &#61; priority;
    this.need &#61; need;
    this.arrived &#61; arrived;
  }
}
</code></pre> 
<p></p> 
<h4>Python算法源码</h4> 
<p>Pytho可以基于queue.PriorityQueue来实现优先队列&#xff0c;但是queue.PriorityQueue的自定义排序不支持函数参数传入&#xff0c;而是只能基于queue.PriorityQueue加入的元素的自身比较器&#xff08;如__lt__和__gt__&#xff09;来排序</p> 
<pre><code class="language-python">import queue


class Task:
    def __init__(self, taskId, priority, need, arrived):
        self.taskId &#61; taskId
        self.priority &#61; priority
        self.need &#61; need
        self.arrived &#61; arrived

    def __gt__(self, other):
        if self.priority !&#61; other.priority:
            return other.priority &gt; self.priority
        else:
            return self.arrived &gt; other.arrived


# 算法入口
def getResult(tasks):
    pq &#61; queue.PriorityQueue()

    pq.put(tasks.pop(0))
    curTime &#61; pq.queue[0].arrived  # curTime记录当前时刻

    while len(tasks) &gt; 0:
        curtTask &#61; pq.queue[0]  # 当前正在运行的任务curtTask
        nextTask &#61; tasks.pop(0)  # 下一个任务nextTask

        curTask_endTime &#61; curTime &#43; curtTask.need  # 当前正在运行任务的“理想”结束时间

        # 如果当前正在运行任务的理想结束时间  超过了  下一个任务的开始时间
        if curTask_endTime &gt; nextTask.arrived:
            curtTask.need -&#61; nextTask.arrived - curTime  # 先不看优先级&#xff0c;先将当前任务可以运行的时间减去
            curTime &#61; nextTask.arrived
        # 如果当前正在运行任务的理想结束时间  没有超过  下一个任务的开始时间&#xff0c;则当前任务可以执行完
        else:
            pq.get()
            print(f&#34;{curtTask.taskId} {curTask_endTime}&#34;)  # 打印执行完的任务的id和结束时间
            curTime &#61; curTask_endTime

            # 如果当前任务结束时&#xff0c;下一次任务还没有达到&#xff0c;那么存在CPU空转(即idle)
            if nextTask.arrived &gt; curTask_endTime:
                # 此时&#xff0c;我们应该从优先队列中取出最优先的任务出来执行&#xff0c;逻辑同上
                while pq.qsize() &gt; 0:
                    idleTask &#61; pq.queue[0]
                    idleTask_endTime &#61; curTime &#43; idleTask.need

                    if idleTask_endTime &gt; nextTask.arrived:
                        idleTask.need -&#61; nextTask.arrived - curTime
                        break
                    else:
                        pq.get()
                        print(f&#34;{idleTask.taskId} {idleTask_endTime}&#34;)
                        curTime &#61; idleTask_endTime

                curTime &#61; nextTask.arrived

        pq.put(nextTask)

    # 所有任务都加入优先队列后&#xff0c;我们就可以按照优先队列的安排&#xff0c;顺序取出任务来执行了
    while pq.qsize() &gt; 0:
        pollTask &#61; pq.get()
        pollTask_endTime &#61; curTime &#43; pollTask.need
        print(f&#34;{pollTask.taskId} {pollTask_endTime}&#34;)
        curTime &#61; pollTask_endTime


# 输入获取
tasks &#61; []
while True:
    task &#61; input()
    if task &#61;&#61; &#34;&#34;:
        getResult(tasks)
        break
    else:
        tmp &#61; list(map(int, task.split()))
        task &#61; Task(tmp[0], tmp[1], tmp[2], tmp[3])
        tasks.append(task)
</code></pre>
                </div>
        </div>
        <div id="treeSkill"></div>
        <div id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"></div>
    <script>
  $(function() {
    setTimeout(function () {
      var mathcodeList = document.querySelectorAll('.htmledit_views img.mathcode');
      if (mathcodeList.length > 0) {
        for (let i = 0; i < mathcodeList.length; i++) {
          if (mathcodeList[i].naturalWidth === 0 || mathcodeList[i].naturalHeight === 0) {
            var alt = mathcodeList[i].alt;
            alt = '\\(' + alt + '\\)';
            var curSpan = $('<span class="img-codecogs"></span>');
            curSpan.text(alt);
            $(mathcodeList[i]).before(curSpan);
            $(mathcodeList[i]).remove();
          }
        }
        MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
      }
    }, 1000)
  });
</script>
</div></html>